/************************************************************************************
<GoSlowDetection>  Copyright (C) <2021>  <Tao Kiang>
    This program comes with ABSOLUTELY NO WARRANTY;
    This is free software, and you are welcome to redistribute it
    under certain conditions;

    You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

    The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
************************************************************************************/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QAction>
#include "myhook.h"
#include <QTimer>
#include <QScreen>
#include <QPropertyAnimation>
#include <QMouseEvent>
#include <QDateTime>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    :QMainWindow(parent)
    ,ui(new Ui::MainWindow)
    ,startRunTime(QDateTime::currentDateTime())
    ,mNoClickTime(0)
    ,mPressFlag(0)
    ,mKeyCount(0)
    ,mMouseCount(0)
{
    ui->setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SubWindow);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setWindowTitle("Go-slow Detection");
    ui->label_key->setText("0");
    ui->label_mouse->setText("0");
    mSetting.brush.setColor(QColor(255,215,0, 255));
    QTimer::singleShot(3000,this,[=](){
        mSetting.brush.setColor(HY_COLOR);
        this->update();
    });

    connect(&mTimer,&QTimer::timeout,this,[=](){
        mNoClickTime ++;
        if(mNoClickTime == 20)
        {
            WindowsUpdateWidget *updateWidget = new WindowsUpdateWidget;
            updateWidget->show();
            connect(updateWidget,&WindowsUpdateWidget::destroyed,this,[=]()
            {
                mNoClickTime = 0;
            });
        }
        if(mSetting.isHyaline)
            mSetting.brush.setColor(QColor(255,150-mNoClickTime*7,150-mNoClickTime*7,80 + mNoClickTime*8));
        else
            mSetting.brush.setColor(QColor(255,250-mNoClickTime*12,250-mNoClickTime*12,255));
        this->update();
    });
    mTimer.setTimerType(Qt::VeryCoarseTimer);   //设置非常差精度的定时器
    mTimer.start(CHECK_TIME);

    //钩子安装初始化
    MyHook::instance()->installHook(MyHook::eMouseKey);
    connect(MyHook::instance(),&MyHook::keyPress,this,[=](){
        mKeyCount ++;
        ui->label_key->setText(QString::number(mKeyCount));
        //addMapCount(keyMapCount);
        clickOperator();
    });
    connect(MyHook::instance(),&MyHook::mousePress,this,[=](){
        mMouseCount ++;
        ui->label_mouse->setText(QString::number(mMouseCount));
        //addMapCount(mouseMapCount);
        clickOperator();
    });

    //配置信息初始化
    mSetting.autoRunFlag = isAutoRun(QApplication::applicationFilePath());  //判断进程是否注册开机启动
    QSize screenSize = QGuiApplication::primaryScreen()->size();    //获取当前屏幕的分辨率
    mSetting.boundSize = screenSize - this->size();                          //计算可移动的边界大小

    //插件
    mPlugManage.loadAllPlugin();
}

void MainWindow::clickOperator()
{
    mTimer.setInterval(CHECK_TIME);
    mNoClickTime = 0;
    if(mSetting.isHyaline)   mSetting.brush.setColor(HY_COLOR);
    else            mSetting.brush.setColor(COLOR);
    this->update();
}

void MainWindow::addMapCount(QMap<QString,quint64> &map)
{
    //天-时，不可连续运行一个月
    QString timeKey = QString("%1-%2").arg(QDate::currentDate().day()).arg(QTime::currentTime().hour());
    map[timeKey] ++;
}

MainWindow::~MainWindow()
{
    qDebug()<<Q_FUNC_INFO<<"relase MainWindow";
    mTimer.stop();
    mPlugManage.unloadAllPlugin();
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    mPressFlag = 1;
    mPressPos = event->pos();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton)
    {
        showMenu(mapToGlobal(event->pos()));
    }
    else if(event->button() == Qt::LeftButton)
    {
        mPressFlag = 0;
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if(!mPressFlag)   //不是左键按下，不产生移动效果
        return ;
    QPoint movePos = event->pos() - mPressPos;
    int x = this->x() + movePos.x();
    int y = this->y() + movePos.y();

    if(x < mSetting.attractWidth)   x = 0;
    if(x  > mSetting.boundSize.width() - mSetting.attractWidth) x = mSetting.boundSize.width();

    if(y < 20)   y = 0;
    if(y  > mSetting.boundSize.height() - mSetting.attractWidth) y = mSetting.boundSize.height();

    this->move(x,y);
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing); //抗锯齿，绘制出来看起来不会有楼梯形状的锯齿感
    painter.setBrush(mSetting.brush);    //使用画刷
    painter.setPen(Qt::NoPen);
    painter.drawRoundedRect(0,0,width(),height(),3,3);
}

#include "overviewwindow.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QRect>
#include <lightMessage.h>
void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    static bool haveOpenWindows = 0;    //识别当前界面是否被创建并打开
    if(haveOpenWindows)
        return ;
    haveOpenWindows = 1;
    OverviewWindow *overview = new OverviewWindow(startRunTime,this);
    overview->show();
    //载入窗口的动画
    QPropertyAnimation *pAnimation = new QPropertyAnimation(overview,"geometry",this);
    pAnimation->setDuration(1000);
    pAnimation->setEasingCurve(QEasingCurve::OutBounce);
    pAnimation->setStartValue(QRect(this->x(),this->y()
                              ,overview->width()/2,overview->height()/4));
    QDesktopWidget *desktop = QApplication::desktop();
    pAnimation->setEndValue(QRect((desktop->width()-this->width())/2
                            ,(desktop->height()-this->height())/2
                            ,overview->width()
                            ,overview->height()));
    pAnimation->start();
    connect(overview,&OverviewWindow::closeThis,this,[=]()
    {
        //关闭窗口的动画
        pAnimation->setEasingCurve(QEasingCurve::OutQuad);
        pAnimation->setStartValue(QRect(overview->x(),overview->y(),overview->width(),overview->height()));
        pAnimation->setEndValue(QRect(this->x(),this->y(),overview->width()/2,overview->height()/4));
        pAnimation->start();
        connect(pAnimation,&QPropertyAnimation::finished,[=]{
            delete overview;
            delete pAnimation;
            haveOpenWindows = 0;
        });
    });
}
//鼠标进入软件范围和跳出软件范围事件
void MainWindow::enterEvent(QEvent *)
{
//    ui->label_keyLog->show();
//    ui->label_mouseLog->show();
//    this->setMaximumSize( QSize(150,31));
//    this->setMinimumSize( QSize(150,31));
}
void MainWindow::leaveEvent(QEvent *)
{
//    ui->label_keyLog->hide();
//    ui->label_mouseLog->hide();
//    this->setMaximumSize( QSize(80,10));
//    this->setMinimumSize( QSize(80,10));
}

#include <QMenu>
#include <QCheckBox>
void MainWindow::showMenu(const QPoint &pos)
{
    QMenu menu;
    loadSysMenu(menu);
    loadPluginMenu(menu);
    menu.exec(pos);
}

//加载系统菜单内容
void MainWindow::loadSysMenu(QMenu &menu)
{
    //===================
    if(mSetting.isHyaline)   //透明情况
    {
        menu.addAction(QIcon(":/new/prefix1/resource/back.png"),"背景非透明",[=](){
            mSetting.isHyaline = 0;
            mSetting.brush.setColor(COLOR);
            this->update();
        });
    }
    else
    {
        menu.addAction(QIcon(":/new/prefix1/resource/back.png"),"背景透明",[=](){
            mSetting.isHyaline = 1;
            mSetting.brush.setColor(HY_COLOR);
            this->update();
        });
    }
    //===================
    menu.addAction(QIcon(":/new/prefix1/resource/clear.png"),"清空计数",[=]()
    {
        cleanCount();
    });
    //===================
    if(!mSetting.autoRunFlag)
    {
        menu.addAction(QIcon(":/new/prefix1/resource/run.png"),"开机启动",[=](){
            setProcessAutoRun(QApplication::applicationFilePath(),1);
            mSetting.autoRunFlag = 1;
        });
    }
    else
    {
        menu.addAction(QIcon(":/new/prefix1/resource/stop.png"),"取消开机启动",[=](){
            setProcessAutoRun(QApplication::applicationFilePath(),0);
            mSetting.autoRunFlag = 0;
        });
    }
    //===================
    menu.addAction(QIcon(":/new/prefix1/resource/quit.png"),"退出",[=]()
    {
        closeApp();
    });
}


//加载插件菜单内容
void MainWindow::loadPluginMenu(QMenu &menu)
{
    QHash<QString, PluginInterface *> allPlugin= mPlugManage.getAllPlugin();
    QStringList pluginFiles = allPlugin.keys();
    QHash<QString, PluginInterface *>::iterator it = allPlugin.begin();
    for(;it != allPlugin.end();it ++)
    {
        PluginInterface *plugin = it.value();
        menu.addAction(plugin->getIcon(),plugin->getName(),[=](){
            qDebug()<<Q_FUNC_INFO<<"clicked menu : "<<plugin->getName();
            QWidget *pluginWidget = plugin->creactUi(this);
            if(pluginWidget)
                pluginWidget->show();
        });
    }
}

//关闭软件请求
void MainWindow::closeApp()
{
    int sreenW = QApplication::desktop()->width();
    int sreenH = QApplication::desktop()->height();
    int posX = qrand()%(sreenW - 200);
    int posY = qrand()%(sreenH-500) + 300;
    static int closeCount = 0;      //用于关闭时的躲闪功能
    if(closeCount == 0)
    {
        this->move(posX,posY);
        LightMessage::information(this,"哼！我跳！我跳！",2000,"16px");
        QTimer::singleShot(30000,this,[=](){
            closeCount = 0;
        });
    }
    else if(closeCount == 1)
    {
        this->move(posX,posY);
        LightMessage::information(this,"...我再跳！！！");
    }
    else if(closeCount >= 2)
    {
        LightMessage::information(nullptr,"呵...拜拜了您！",2000,"16px");
        MyHook::instance()->relase();
        this->destroy(1);
    }
    closeCount ++;
}
//清空计数
#include <QMessageBox>
void MainWindow::cleanCount()
{
    QMessageBox::StandardButton button = QMessageBox::question(this,"疑问","是否清空计数");
    if(button == QMessageBox::No)
        return ;
    mKeyCount = 0;
    mMouseCount = 0;
    //keyMapCount.clear();
    //mouseMapCount.clear();
    ui->label_key->setText(QString::number(mKeyCount));
    ui->label_mouse->setText(QString::number(mMouseCount));
}

#include <QSettings>
#include <QFileInfo>
#include <QDir>
/*******************************
 * 时间：2021年12月1日
 * 功能：设置/取消 进程开机自动启动函数
 * 参数：
    1、appPath：需要设置/取消的自启动软件的“绝对路径”
    2、flag：   设置/取消自启动标志位，1为设置，0为取消,默认为设置
*******************************/
//注册表路径需要使用双反斜杠
#define AUTO_RUN "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
void MainWindow::setProcessAutoRun(const QString &appPath,bool flag)
{
    QSettings settings(AUTO_RUN, QSettings::NativeFormat);

    //以程序名称作为注册表中的键,根据键获取对应的值（程序路径）
    QFileInfo fInfo(appPath);
    QString name = fInfo.baseName();    //键-名称

    //如果注册表中的路径和当前程序路径不一样，则表示没有设置自启动或本自启动程序已经更换了路径
    QString oldPath = settings.value(name).toString(); //获取目前的值-绝对路劲
    QString newPath = QDir::toNativeSeparators(appPath);    //toNativeSeparators函数将"/"替换为"\"
    if(flag)
    {
        if (oldPath != newPath)
            settings.setValue(name, newPath);
    }
    else
       settings.remove(name);
}

//判断进程是否为开机自动启动
bool MainWindow::isAutoRun(const QString &appPath)
{
    QSettings settings(AUTO_RUN, QSettings::NativeFormat);
    QFileInfo fInfo(appPath);
    QString name = fInfo.baseName();
    QString oldPath = settings.value(name).toString();
    QString newPath = QDir::toNativeSeparators(appPath);
    return (settings.contains(name) && newPath == oldPath);
}





